/* NoX (NoC Simulator)
 *
 * Dept. of Computer Science & Engineering, Pennsylvania State University.
 * All Rights Reserved.
 *  
 * 1. License     
 * NoX is distributed free of charge for academic, educational, noncommercial 
 * research purposes as long as this notice in its entirety is preserved in
 * every file included in this package.
 * All commercial use of this program requires separate licence. Contact the
 * author for details.
 * 
 * 2. All the publications that used the simulation results generated by the 
 * NoX should notify the author of the publication information and put 
 * following reference.
 *
 *  http://www.cse.psu.edu/~dpark/nox/
 * 
 * 3. Modification of the source code is permitted and encouraged as long as 
 * it follows the terms described in this copyright notice.
 *
 * 4. The author is not responsible for any problems caused by possible errors
 * of the NoX package. Therefore, users should verify the simulation result
 * before using it in their publication.
 *
 * Dept. of Computer Science & Engineering, Pennsylvania State University.
 * Contact: dpark@cse.psu.edu 
 * 
 * 6. If problems are found with the NoX package, please send an email to the
 * author for discussion and correction.

 */

/* Update History
 *
 *
 */


#ifndef ROUTER_H
#define ROUTER_H

#include "flit_move.h"
#include "power.h"

#define R_V         0
#define R_P         1
#define R_PV        2

#define RR          0
#define LRU         1
#define PR          2

#define VC_IDLE     0 // VC is idle
#define VC_ROUTING  1 // Routing Done
#define VC_VA_DONE  2 // VA is done 
#define VC_SA_DONE  3 // SA is done 


#define VC_IDLE_TMP     4 // VC is idle
#define VC_ROUTING_TMP  5 // Routing Done
#define VC_VA_DONE_TMP  6 // VA is done 
#define VC_SA_DONE_TMP  7 // SA is done 
#define VC_SA_DONE_TMP1 8 // SA is done 
#define VC_SA_DONE_TMP2 9 // SA is done 
#define VC_SA_DONE_TMP3 10 // SA is done 

#define VC_BUSY     20

#define MAX_COLS    8
#define MAX_ROWS    8 
#define MAX_NODES   (MAX_COLS * MAX_ROWS)

#define XBAR_SWITCH 0
#define BUS_SWITCH  1

// definition for the ready flag.

#define MAX_PC	    5 // number of PCs per router (including inj/ejt channel).
#define MAX_VC	    64 // number of VCs per PC.
#define MAX_NIC_PC  1 // number of PCs connected between NIC and ROUTER.
#define MAX_PRI_LEVELS 16

#define VC_SET      0
//#define RESP_RQ_TRAFFIC 1
#define ROUTER_INPUT_BUF_NON_UNIFORM 0

#define ROUTER_INPUT_BUF_SIZE  router_inp_buf_size 
#define HYB_VC_RATIO 4 

//#define CLINE_SIZE_BITS 1024

// Direction
#define WEST        0
#define NORTH       1
#define EAST        2
#define SOUTH       3

#define LEFT	    0
#define UP	      1
#define RIGHT	    2
#define DOWN	    3
#define THIS      4

//Both way edge
#define EDGE       -1
//One way edge
//if we assign EDGE then no buffer will be given on
//either direction thus we assign a special id for unidirectional
//links
#define EDGE_UNIDIRECTION    -2

#define RESERVED    0
#define CANDIDATE   1
#define AVAILABLE   2
#define RESV_BLOCK  3 // path is reserved, but buffer is not ready.

#define SECDED_CHK_TIME            0.0L // Encoding time for FEC (SECDED)
#define CRC_CHK_TIME               0.0L // For all schemes except FEC
#define HBH_ORDERING_TIME          0.0L // For the Hop-by-Hop scheme
#define HBH_BUF_SIZE               3    // We need 3 HBH buffers (see proposed HBH scheme).

#define max(a,b)  ((a) > (b) ? (a) : (b))

// Adaptive routing specific
// Blocking cycle threshold at which point the flit switches to the deterministic escape channel.
#define ADAP_THRES  25 


typedef enum {
  HEALTHY = 0,
  GOOD    = 1,
  BAD     = 2,
  WORSE   = 3,
  TRAPPED = 4,
  FAIL    = 5
} node_label_t;

typedef enum {
  BLOCK = 1,
  NOBLOCK = 0
} block_flag_t;

typedef enum {
  RESV = 1,
  UNRESV = 0
} resv_flag_t;


typedef struct 
{
  node_label_t health_status;

  // Stores Proximity-Aware routing information.
  // Refer to route_proximity_aware.c/h file.
  short int FA_blocked_info[4];
  short int FA_route_info[4];
  short int FA_link_info[4];
  short int FA_neighbor_info[4];
  short int FA_direction_info[4][4];
} router_t;

typedef struct 
{
  int vc_stat;
  int out_pc;
  int out_pc_cand[MAX_PC];
  int out_vc;
  int out_vc_cand[MAX_VC];
  int priority_id;
} vc_info_t;

// Using bit-field, define ready_flag type.
typedef struct ready_flag
{
  unsigned ninbuf:	     1; // NIC input buf
  unsigned noutbuf:	     1; // NIC output buf
  unsigned arbiter:	     1; // router arbiter (between stage 1 and 2). 
  unsigned arbiter_tmp:	     1; // router arbiter (between stage 1 and 2) temporary (overwrite arbiter at the end of each cycle). 
  unsigned xbarin:           1; // router crossbar input
  unsigned xbarout:          1; // router crossbar output
  int rinbuf;                   // router input buf
  int pinbuf;
} ready_flag_t;

typedef struct has_ongoing_flit
{
  unsigned arbiter:          1; // arbiter
  unsigned xbar:             1; // xbar   
  unsigned nic:              1; // nic
} has_flit_t;

typedef struct xbar_out
{
  int pc;                       // destination pc of the xbar
  int vc;                       // destination vc of the xbar
  int next_pc;                  // destination pc of the xbar. Used in header flit only.
  int next_vc;                  // destination vc of the xbar. Used in header flit only.
} xbar_out_t;

typedef struct chan_stat
{
  int status;
  unsigned int wait_time;
  int selected_input_pc;
  int selected_input_vc;
} chan_stat_t;

//topology sub network type for the router
//can be local bus based or global or uniform flat topology

#define FLAT   0
#define LOCAL  1
#define GLOBAL 2

typedef struct {

  short num_pc;
  short num_nic_pc;
  short num_vc;
  short type;
  
  float pd_p_1_arb;
  float pd_v_1_arb;
  float pd_pv_1_arb;

  float pl_p_1_arb;
  float pl_v_1_arb;
  float pl_pv_1_arb;

} router_info_t;  
  
typedef struct butterfly
{
  int k;
  int n;
} butterfly_t;

class source_queue_t{
  public :
         unsigned int id;
         int batch_id;
         bool done;
         float slack;
         long long inj_tm;
        source_queue_t(unsigned int packet_id, int bid, bool status,float s);
};

typedef struct sort_struct{
  double val;
  unsigned pos;
}sort_t;

typedef struct {
int dst;
long long clock;
} trace_line_t;

void stage1(); // This stage handles decoding and making routing decision.
void stage3(); // This stage handles data transfer through crossbar. 
void VA_stage();
void SA_stage();

// Routing algorithms
void  deterministic_route(int cn, int dn, int pc, int vc, int* dest_pc, int* dest_vc, flit_t *flit_ptr);
void     west_first_route(int cn, int dn, int pc, int vc, int* dest_pc, int* dest_vc);
void fully_adaptive_route(int cn, int dn, int pc, int vc, int* dest_pc, int* dest_vc);
void     fail_aware_route(int cn, int dn, int pc, int vc, int* dest_pc, int* dest_vc);

// Arbiter
int RR_arbiter(int *req, int *win, int num_set, int set_size);
int PR_arbiter(int *req, int *win, long long *pri, long long *age, int num_set, int set_size);
int LRU_arbiter(int *req, int *win, int num_set, int set_size);
int XShare_arbiter(int *req, int *last_win, int n_set, int set_size);
#endif
